{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 条件和条件语句"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Enter a number: 3\n",
      "The number is positive\n"
     ]
    }
   ],
   "source": [
    "# elif子句\n",
    "num = int(input('Enter a number: '))\n",
    "if num > 0:\n",
    "    print('The number is positive')\n",
    "elif num < 0:\n",
    "    print('The number is negative')\n",
    "else:\n",
    "    print('The number is zero')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "What is your name? Ivan\n",
      "Hello, stranger\n"
     ]
    }
   ],
   "source": [
    "# 代码块嵌套\n",
    "name = input('What is your name? ') \n",
    "if name.endswith('Gumby'):\n",
    "    if name.startswith('Mr.'):\n",
    "        print('Hello, Mr. Gumby') \n",
    "    elif name.startswith('Mrs.'):\n",
    "        print('Hello, Mrs. Gumby')\n",
    "    else:\n",
    "        print('Hello, Gumby') \n",
    "else:\n",
    "    print('Hello, stranger')\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- is 和 == 的区别\n",
    "\n",
    "is检查两个对象是否相同（而不是相等），下面例子中变量x和y指向同一个列表，而z指向另一个列表（其中包含的值以及这些值的排列顺序都与前一个列表相同）。这两个列表虽然相等，但并非同一个对象。\n",
    "\n",
    "总之，==用来检查两个对象是否相等，而 is 用来检查两个对象是否相同（是同一个对象）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# is和 == 的区别\n",
    "x = y = [1, 2, 3]\n",
    "z = [1, 2, 3]\n",
    "x == y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x == z "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x is y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x is z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "编写一个程序，让它读取一个数，并检查这个数是否位于1~10（含）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Enter a number between 1 and 10: 9\n",
      "Great!\n"
     ]
    }
   ],
   "source": [
    "# 方法一：\n",
    "number = int(input('Enter a number between 1 and 10: '))\n",
    "if number <= 10:\n",
    "    if number >= 1:\n",
    "        print('Great!')\n",
    "    else:\n",
    "        print('Wrong！')\n",
    "else:\n",
    "    print('Wrong!')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Enter a number between 1 and 10: 11\n",
      "Wrong\n"
     ]
    }
   ],
   "source": [
    "# 方法二：\n",
    "number = int(input('Enter a number between 1 and 10: '))\n",
    "if number <= 10 and number >= 1: \n",
    "    print('Great')\n",
    "else:\n",
    "    print('Wrong')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 短路逻辑和条件表达式\n",
    "\n",
    "布尔运算符有个有趣的特征：只做必要的计算。例如，仅当x和y都为真时，表达式x and \n",
    "y才为真。因此如果x为假，这个表达式将立即返回假，而不关心y。实际上，如果x为假，这\n",
    "个表达式将返回x，否则返回y。（这将提供预期的结果，你明白了其中的原理吗？）这种行为称为短路逻辑（或者延迟求值）：布尔运算符常被称为逻辑运算符，如你所见，在有些情况下将“绕过”第二个值。对于运算符or，情况亦如此。在表达式x or y中，如果x为真，就返回x，否则返回y。（你明白这样做合理的原因吗？）请注意，这意味着位于布尔运算符后面的代码（如函数调用）可能根本不会执行。像下面这样的代码就利用了这种行为：\n",
    "\n",
    "        name = input('Please enter your name: ') or '<unknown>' \n",
    "    \n",
    "如果没有输入名字，上述or表达式的结果将为'<unknown>'。在很多情况下，你都宁愿使\n",
    "用条件表达式，而不耍这样的短路花样。不过前面这样的语句确实有其用武之地。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 断言\n",
    "\n",
    "if语句有一个很有用的“亲戚”，其工作原理类似于下面的伪代码：\n",
    "\n",
    "    if not condition: \n",
    "        crash program\n",
    " \n",
    "问题是，为何要编写类似于这样的代码呢？因为让程序在错误条件出现时立即崩溃胜过以后\n",
    "再崩溃。基本上，你可要求某些条件得到满足（如核实函数参数满足要求或为初始测试和调试提供帮助），为此可在语句中使用关键字assert。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "age = 10\n",
    "assert 0 < age < 100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "ename": "AssertionError",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAssertionError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-17-ed325dd67701>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[0mage\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[1;36m0\u001b[0m \u001b[1;33m<\u001b[0m \u001b[0mage\u001b[0m \u001b[1;33m<\u001b[0m\u001b[1;36m100\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mAssertionError\u001b[0m: "
     ]
    }
   ],
   "source": [
    "age = -1\n",
    "assert 0 < age <100"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果知道必须满足特定条件，程序才能正确地运行，可在程序中添加assert语句充当检查点，这很有帮助。\n",
    "\n",
    "还可在条件后面添加一个字符串，对断言做出说明。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "ename": "AssertionError",
     "evalue": "The age must be realistic",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mAssertionError\u001b[0m                            Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-18-faf354b692a1>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[0mage\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[1;32massert\u001b[0m \u001b[1;36m0\u001b[0m \u001b[1;33m<\u001b[0m \u001b[0mage\u001b[0m \u001b[1;33m<\u001b[0m\u001b[1;36m100\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'The age must be realistic'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mAssertionError\u001b[0m: The age must be realistic"
     ]
    }
   ],
   "source": [
    "age = -1\n",
    "assert 0 < age <100, 'The age must be realistic' "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 循环\n",
    "## while循环"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "7\n",
      "8\n",
      "9\n",
      "10\n",
      "11\n",
      "12\n",
      "13\n",
      "14\n",
      "15\n",
      "16\n",
      "17\n",
      "18\n",
      "19\n",
      "20\n",
      "21\n",
      "22\n",
      "23\n",
      "24\n",
      "25\n",
      "26\n",
      "27\n",
      "28\n",
      "29\n",
      "30\n",
      "31\n",
      "32\n",
      "33\n",
      "34\n",
      "35\n",
      "36\n",
      "37\n",
      "38\n",
      "39\n",
      "40\n",
      "41\n",
      "42\n",
      "43\n",
      "44\n",
      "45\n",
      "46\n",
      "47\n",
      "48\n",
      "49\n",
      "50\n",
      "51\n",
      "52\n",
      "53\n",
      "54\n",
      "55\n",
      "56\n",
      "57\n",
      "58\n",
      "59\n",
      "60\n",
      "61\n",
      "62\n",
      "63\n",
      "64\n",
      "65\n",
      "66\n",
      "67\n",
      "68\n",
      "69\n",
      "70\n",
      "71\n",
      "72\n",
      "73\n",
      "74\n",
      "75\n",
      "76\n",
      "77\n",
      "78\n",
      "79\n",
      "80\n",
      "81\n",
      "82\n",
      "83\n",
      "84\n",
      "85\n",
      "86\n",
      "87\n",
      "88\n",
      "89\n",
      "90\n",
      "91\n",
      "92\n",
      "93\n",
      "94\n",
      "95\n",
      "96\n",
      "97\n",
      "98\n",
      "99\n",
      "100\n"
     ]
    }
   ],
   "source": [
    "# 打印1~100的整数\n",
    "x = 1\n",
    "while x<= 100:\n",
    "    print(x)\n",
    "    x += 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Please enter your name:  \n",
      "Please enter your name: 1\n",
      "Hello, 1!\n"
     ]
    }
   ],
   "source": [
    "# 使用循环确保用户输入名字\n",
    "name = '' \n",
    "while not name or name.isspace(): # 确保用户输入的不是一个空格字符\n",
    "    name = input('Please enter your name: ') \n",
    "print('Hello, {}!'.format(name))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## for循环\n",
    "while语句非常灵活，可用于在条件为真时反复执行代码块。这在通常情况下很好，但有时\n",
    "候你可能想根据需要进行定制。一种这样的需求是为序列（或其他可迭代对象）中每个元素执行代码块。\n",
    "\n",
    "基本上，可迭代对象是可使用for循环进行遍历的对象。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "this\n",
      "is\n",
      "an\n",
      "ex\n",
      "parrot\n"
     ]
    }
   ],
   "source": [
    "words = ['this', 'is', 'an', 'ex', 'parrot'] \n",
    "for word in words: \n",
    "    print(word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "range(0, 10)"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "range(0, 10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(range(0, 10))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "7\n",
      "8\n",
      "9\n",
      "10\n",
      "11\n",
      "12\n",
      "13\n",
      "14\n",
      "15\n",
      "16\n",
      "17\n",
      "18\n",
      "19\n",
      "20\n",
      "21\n",
      "22\n",
      "23\n",
      "24\n",
      "25\n",
      "26\n",
      "27\n",
      "28\n",
      "29\n",
      "30\n",
      "31\n",
      "32\n",
      "33\n",
      "34\n",
      "35\n",
      "36\n",
      "37\n",
      "38\n",
      "39\n",
      "40\n",
      "41\n",
      "42\n",
      "43\n",
      "44\n",
      "45\n",
      "46\n",
      "47\n",
      "48\n",
      "49\n",
      "50\n",
      "51\n",
      "52\n",
      "53\n",
      "54\n",
      "55\n",
      "56\n",
      "57\n",
      "58\n",
      "59\n",
      "60\n",
      "61\n",
      "62\n",
      "63\n",
      "64\n",
      "65\n",
      "66\n",
      "67\n",
      "68\n",
      "69\n",
      "70\n",
      "71\n",
      "72\n",
      "73\n",
      "74\n",
      "75\n",
      "76\n",
      "77\n",
      "78\n",
      "79\n",
      "80\n",
      "81\n",
      "82\n",
      "83\n",
      "84\n",
      "85\n",
      "86\n",
      "87\n",
      "88\n",
      "89\n",
      "90\n",
      "91\n",
      "92\n",
      "93\n",
      "94\n",
      "95\n",
      "96\n",
      "97\n",
      "98\n",
      "99\n",
      "100\n"
     ]
    }
   ],
   "source": [
    "# 打印1~100的整数：\n",
    "for number in range(1, 101):\n",
    "    print(number)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Tips: 只要能够使用for循环，就不要使用while循环。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 迭代字典\n",
    "要遍历字典的所有关键字，可像遍历序列那样使用普通的for语句。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x corresponds to 1\n",
      "y corresponds to 2\n",
      "z corresponds to 3\n"
     ]
    }
   ],
   "source": [
    "d = {'x': 1, 'y': 2, 'z': 3} \n",
    "for key in d: \n",
    "    print(key, 'corresponds to', d[key])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "也可使用keys等字典方法来获取所有的键。如果只对值感兴趣，可使用d.values。你可能还\n",
    "记得，d.items以元组的方式返回键值对。for循环的优点之一是，可在其中使用序列解包。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x corresponds to 1\n",
      "y corresponds to 2\n",
      "z corresponds to 3\n"
     ]
    }
   ],
   "source": [
    "for key, value in d.items(): \n",
    "    print(key, 'corresponds to', value)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 注意：\n",
    "字典元素的排列顺序是不确定的。换而言之，迭代字典的键或值时，一定会处理所有的\n",
    "键或值，但不知道处理的顺序。如果顺序很重要，可将键或值存储在一个列表中并对列\n",
    "表排序，再进行迭代。要让映射记住其项的插入顺序，可使用模块collections中的\n",
    "OrderedDict类。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 一些迭代工具\n",
    "- 1.并行迭代\n",
    "\n",
    "有时候，你可能想同时迭代两个序列。假设有下面两个列表："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "names = ['anne', 'beth', 'george', 'damon'] \n",
    "ages = [12, 45, 32, 102]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果要打印名字和对应的年龄，可以像下面这样做："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "anne is 12 years old\n",
      "beth is 45 years old\n",
      "george is 32 years old\n",
      "damon is 102 years old\n"
     ]
    }
   ],
   "source": [
    "for i in range(len(names)):\n",
    "    print(names[i], 'is', ages[i], 'years old')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "i是用作循环索引的变量的标准名称。一个很有用的并行迭代工具是内置函数 __zip__ ，它将两个\n",
    "序列“缝合”起来，并返回一个由元组组成的序列。返回值是一个适合迭代的对象，要查看其内容，可使用list将其转换为列表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('anne', 12), ('beth', 45), ('george', 32), ('damon', 102)]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(zip(names, ages))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "anne is 12 years old\n",
      "beth is 45 years old\n",
      "george is 32 years old\n",
      "damon is 102 years old\n"
     ]
    }
   ],
   "source": [
    "# 在循环中将元组解包\n",
    "for name, age in zip(names, ages):\n",
    "    print(name, 'is', age, 'years old')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "函数zip可用于“缝合”任意数量的序列。需要指出的是，当序列的长度不同时，函数zip将\n",
    "在最短的序列用完后停止“缝合”。`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    " list(zip(range(5), range(100000000)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 2.迭代时获取索引\n",
    "\n",
    "在有些情况下，你需要在迭代对象序列的同时获取当前对象的索引。例如，你可能想替换一\n",
    "个字符串列表中所有包含子串'xxx'的字符串。当然，完成这种任务的方法有很多，但这里假设你要像下面这样做："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'strings' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-34-e83c475a9ef7>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[1;32mfor\u001b[0m \u001b[0mstring\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mstrings\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      2\u001b[0m     \u001b[1;32mif\u001b[0m \u001b[1;34m'xxx'\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mstring\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      3\u001b[0m         \u001b[0mindex\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mstrings\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mstring\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;31m# 在字符串列表中查找字符串\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      4\u001b[0m         \u001b[0mstrings\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mindex\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;34m'[censored]'\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      5\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mNameError\u001b[0m: name 'strings' is not defined"
     ]
    }
   ],
   "source": [
    "for string in strings: \n",
    "    if 'xxx' in string: \n",
    "        index = strings.index(string) # 在字符串列表中查找字符串\n",
    "        strings[index] = '[censored]'\n",
    "        "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "range(99, 0, -1)"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "range(99, 0, -1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[99,\n",
       " 98,\n",
       " 97,\n",
       " 96,\n",
       " 95,\n",
       " 94,\n",
       " 93,\n",
       " 92,\n",
       " 91,\n",
       " 90,\n",
       " 89,\n",
       " 88,\n",
       " 87,\n",
       " 86,\n",
       " 85,\n",
       " 84,\n",
       " 83,\n",
       " 82,\n",
       " 81,\n",
       " 80,\n",
       " 79,\n",
       " 78,\n",
       " 77,\n",
       " 76,\n",
       " 75,\n",
       " 74,\n",
       " 73,\n",
       " 72,\n",
       " 71,\n",
       " 70,\n",
       " 69,\n",
       " 68,\n",
       " 67,\n",
       " 66,\n",
       " 65,\n",
       " 64,\n",
       " 63,\n",
       " 62,\n",
       " 61,\n",
       " 60,\n",
       " 59,\n",
       " 58,\n",
       " 57,\n",
       " 56,\n",
       " 55,\n",
       " 54,\n",
       " 53,\n",
       " 52,\n",
       " 51,\n",
       " 50,\n",
       " 49,\n",
       " 48,\n",
       " 47,\n",
       " 46,\n",
       " 45,\n",
       " 44,\n",
       " 43,\n",
       " 42,\n",
       " 41,\n",
       " 40,\n",
       " 39,\n",
       " 38,\n",
       " 37,\n",
       " 36,\n",
       " 35,\n",
       " 34,\n",
       " 33,\n",
       " 32,\n",
       " 31,\n",
       " 30,\n",
       " 29,\n",
       " 28,\n",
       " 27,\n",
       " 26,\n",
       " 25,\n",
       " 24,\n",
       " 23,\n",
       " 22,\n",
       " 21,\n",
       " 20,\n",
       " 19,\n",
       " 18,\n",
       " 17,\n",
       " 16,\n",
       " 15,\n",
       " 14,\n",
       " 13,\n",
       " 12,\n",
       " 11,\n",
       " 10,\n",
       " 9,\n",
       " 8,\n",
       " 7,\n",
       " 6,\n",
       " 5,\n",
       " 4,\n",
       " 3,\n",
       " 2,\n",
       " 1]"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(range(99, 0, -1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "range(0, 10, 2)"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "range(0, 10, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x * x for x in range(10)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 9, 36, 81]"
      ]
     },
     "execution_count": 40,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[x*x for x in range(10) if x % 3 == 0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[(x, y) for x in range(3) for y in range(3)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 多重继承"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hi, my value is 7\n"
     ]
    }
   ],
   "source": [
    "class Calculator: \n",
    "    def calculate(self, expression): \n",
    "        self.value = eval(expression)\n",
    "        \n",
    "        \n",
    "class Talker: \n",
    "    def talk(self): \n",
    "        print('Hi, my value is', self.value)\n",
    "        \n",
    "        \n",
    "class TalkingCalculator(Calculator, Talker): \n",
    "    pass\n",
    "\n",
    "\n",
    "tc = TalkingCalculator()\n",
    "tc.calculate('1 + 2 * 3')\n",
    "tc.talk()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 接口和内省\n",
    "# 检查所需方法是否存在\n",
    "hasattr(tc, 'talk')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "hasattr(tc, 'fnord')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 检查属性talk是否是可调用的\n",
    "callable(getattr(tc, 'talk', None))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
